//==============================================================================
//
//     DSocketAddress - the socket address wrapper classes in the ofc-library
//
//               Copyright (C) 2004  Dick van Oudheusden
//  
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this library; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//==============================================================================
// 
//  $Date: 2007-11-04 15:29:14 $ $Revision: 1.19 $

//==============================================================================

#include "ofc/DSocketAddress.h"

#ifndef WIN32
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#endif
#include <string.h>

#ifdef WIN32
#define ERRNO      (WSAGetLastError())
#else
#define ERRNO      (errno)
#endif



#if _INTERFACE_

#include "ofc/config.h"

#include "ofc/DText.h"

#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#endif


#define DSA_AF_INET    (AF_INET)         // Inet socket family
#ifndef WIN32
#ifdef  AF_UNIX
#define DSA_AF_UNIX    (AF_UNIX)         // Unix socket family
#endif
#endif
#ifdef  AF_INET6
#define DSA_AF_INET6   (AF_INET6)        // IPv6 socket family
#endif

//
// The DSocketAddressable protocol specifies the methods for a socket address
// 

@protocol DSocketAddressable

//
// Copy the object
// 
// @return the object
// 

- copy;

//
// Free the address
//
// @return the object
//

- free;

//
// Return the last error
// 
// @return the last error
// 

- (int) error;
  
//
// Return the family of the socket address
// 
// @return the family
// 
- (int) family;

//
// Return the socket address
// 
// @return the socket address
// 
- (void *) sockaddr;

//
// Return the size of the socket address
// 
// @return the size
// 
- (int) size;

//
// Return the port (network format)
// 
// @return the port
// 
- (int) port;

//
// Return the host name
// 
// @return a (new) text object with the host name
// 
- (DText *) host;

//
// Set the socket address with an external socket address
// 
// @param addr      the socket address
// @param size      the size of the socket address
// 
// @return success
// 

- (BOOL) sockaddr :(void *) addr :(int) size;

//
// Close the socket address
// 
// @return the object
// 

- close;

@end

  
//
// The DInetSocketAddress class implements a number of methods for using 
// inet socket addresses.
// 

@interface DInetSocketAddress : Object <DSocketAddressable>
{
@private
  struct sockaddr     _address;    // the socket address
  struct sockaddr_in *_inet;       // the cast to inet socket address
  int                 _error;      // the last error (for host method)
}

#endif


@implementation DInetSocketAddress


//// Constructors

//
// Initialise the socket address
//
// @return the object
//

- (DInetSocketAddress *) init
{
  [super init];

  _inet = (struct sockaddr_in *) &_address;
  
  memset(&_address, 0, sizeof(_address));

  _error = 0;
  
  return self;
}

//
// Initialise the socket address with an inet address
// 
// @param address   the inet address
// @param port      the port
//
// @return the object
//

- (DInetSocketAddress *) init :(long) address :(int) port
{
  [self init];
  
  [self set :address :port];
  
  return self;
}

//
// Initialise the socket address with an inet address (b1.b2.b3.b4)
// 
// @param b1        the first  byte of the inet address
// @param b2        the second byte of the inet address
// @param b3        the third  byte of the inet address
// @param b4        the fourth byte of the inet address
// @param port      the port
//
// @return the object
//

- (DInetSocketAddress *) init :(unsigned char) b1 :(unsigned char) b2 :(unsigned char) b3 :(unsigned char) b4 :(int) port
{
  [self init];
  
  [self set :b1 :b2 :b3 :b4 :port];
  
  return self;
}


//// Copy related methods

//
// Copy the object (for protocol)
// 
// @return the object
// 
- copy
{
  return [super copy];
}

//
// Do a shallow copy of the object
// 
// @return the object
// 
- shallowCopy
{
  DInetSocketAddress *copy = [super shallowCopy];
  
  copy->_inet = (struct sockaddr_in *) &(copy->_address);

  return copy;
}


//// Deconstructor

//
// Free the socket object
//
// @return the object
//

- free
{
  return [super free];
}


//// Member services

//
// Return the last error
// 
// @return the last error
// 

- (int) error
{  
  return _error;
}

//
// Return the family of the socket address
// 
// @return the family
// 
- (int) family
{
  return DSA_AF_INET;
}

//
// Return the socket address
// 
// @return the socket address
// 

- (void *) sockaddr
{
  return _inet;
}

//
// Return the size of the socket address
// 
// @return the size
// 

- (int) size
{
  return sizeof(struct sockaddr_in);
}

//
// Return the port (network format)
// 
// @return the port
// 

- (int) port
{
  return _inet->sin_port;
}

//
// Set the port 
// 
// @param port     the port
// 
// @return the object
// 

- (DInetSocketAddress *) port :(int) port
{
  _inet->sin_port = htons(port);
  
  return self;
}

//
// Return the host name 
// 
// @return a (new) text object with the host name (or nil for not found)
// 

- (DText *) host
{
  DText *name = nil;

#if defined(WIN32) || defined(__FreeBSD__)
  struct hostent *host = gethostbyaddr((const char *)_inet, sizeof(struct sockaddr_in), AF_INET);
#else
  struct hostent *host = gethostbyaddr(_inet, sizeof(struct sockaddr_in), AF_INET);
#endif
      
  if (host != NULL)
  {
    name = [DText new];
        
    [name set :host->h_name];
  }
  else
  {
    _error = h_errno;
  }
  
  return name;
}
    

//// Socket address setters

//
// Set the socket address with an inet address
//
// @param address   the inet address
// @param address   the port of the address
//
// @return the object
//

- (DInetSocketAddress *) set :(unsigned long) address :(int) port
{
  _inet->sin_family      = DSA_AF_INET;
  _inet->sin_addr.s_addr = htonl(address);
  _inet->sin_port        = htons(port);

  return self;
}

//
// Set the socket address with an inet address
// 
// @param b1        the first  byte of the inet address
// @param b2        the second byte of the inet address
// @param b3        the third  byte of the inet address
// @param b4        the fourth byte of the inet address
// @param port      the port of the address
//
// @return the object
//

- (DInetSocketAddress *) set :(unsigned char) b1 :(unsigned char) b2 :(unsigned char) b3 :(unsigned char) b4 :(int) port
{
  [self set :((b1 << 24) + (b2 << 16) + (b3 << 8) + b4) :port];

  return self;
}

//
// Get the inet address from the socket address 
// 
// @param b1        the first  byte of the inet address
// @param b2        the second byte of the inet address
// @param b3        the third  byte of the inet address
// @param b4        the fourth byte of the inet address
//
// @return the port (host format)
//

- (int) get :(unsigned char *) b1 :(unsigned char *) b2 :(unsigned char *) b3 :(unsigned char *) b4
{
  unsigned long address = ntohl(_inet->sin_addr.s_addr);
  
  *b1 = (unsigned char) ((address >> 24) & 0xff);
  *b2 = (unsigned char) ((address >> 16) & 0xff);
  *b3 = (unsigned char) ((address >> 8)  & 0xff);
  *b4 = (unsigned char)  (address        & 0xff);
  
  return ntohs(_inet->sin_port);
}

//
// Set the socket address with an inet host
// 
// @param host      the host name for the inet address
// @param port      the port for the address
// 
// @return the object
// 

- (BOOL) host :(const char *) name :(int) port
{
  BOOL ok = NO;
  
  if ((name == NULL) || (*name == EOS))
  {
    WARNING(DW_INVALID_ARG, "name");
  }
  else
  {
    struct hostent *host = 0; 
        
    host = gethostbyname(name);
    
    ok = ((host != NULL) && (host->h_addr_list[0] != NULL) && (host->h_addrtype == AF_INET));
        
    if (ok)
    {
      _inet->sin_family = DSA_AF_INET;
      _inet->sin_addr   = *(struct in_addr *)(host->h_addr_list[0]);
      _inet->sin_port   = htons(port);
    }
    else
    {
      _error = h_errno;
    }
  }
  
  return ok;
}

//
// Set the socket address with an external socket address
// 
// @param addr      the socket address
// @param size      the size of the socket address
// 
// @return success
// 

- (BOOL) sockaddr :(void *) addr :(int) size
{
  BOOL ok = NO;
  
  struct sockaddr_in *inet = (struct sockaddr_in *) addr;
  
  if ((addr == NULL) || (inet->sin_family != DSA_AF_INET))
  {
    WARNING(DW_INVALID_ARG, "addr");
  }
  else if (size != sizeof(struct sockaddr_in))
  {
    WARNING(DW_INVALID_ARG, "size");
  }
  else
  {
    _inet->sin_family = DSA_AF_INET;
    
    memcpy(_inet, addr, sizeof(struct sockaddr_in));
  
    ok = YES;
  }
  
  return ok;
}
      
//
// Set the loopback address for an inet socket address
// 
// @param port      the port
// 
// @return the object
// 
- (DInetSocketAddress *) loopback :(int) port
{
  [self set :INADDR_LOOPBACK :port];
  
  return self;
}

//
// Set the any address for the inet socket address
// 
// @param port      the port
// 
// @return the object
// 
- (DInetSocketAddress *) any :(int) port
{
  [self set :INADDR_ANY :port];
  
  return self;
}

//
// Set the broadcast address for an inet socket address
// 
// @param port      the port
// 
// @return the object
// 
- (DInetSocketAddress *) broadcast :(int) port
{
  [self set :INADDR_BROADCAST :port];
  
  return self;
}

//
// Close the socket address
// 
// @return the object
// 

- (DInetSocketAddress *) close
{
  return self;
}

@end



#if _INTERFACE_

#ifdef DSA_AF_UNIX
//
// The DUnixSocketAddress class implements a number of methods for using 
// unix (file) socket addresses.
// 
 
@interface DUnixSocketAddress : Object <DSocketAddressable>
{
@private
  struct sockaddr     _address;    // the address
  struct sockaddr_un *_unix;       // the unix cast to address
  int                 _size;       // the size of sockaddr
  int                 _error;      // always 0
}

#endif
#endif



#ifdef DSA_AF_UNIX

@implementation DUnixSocketAddress


//// Constructors

//
// Initialise the socket address
//
// @return the object
//

- (DUnixSocketAddress *) init
{
  [super init];

  _unix = (struct sockaddr_un *) &_address;
  
  memset(&_address, 0, sizeof(_address));

  _size   = 0;
  _error  = 0;
  
  return self;
}

//
// Initialise the socket address with a filename
//
// @param filename  the name of the file
//
// @return the object
//

- (DUnixSocketAddress *) init :(const char *) filename
{
  [self init];

  [self filename :filename];
  
  return self;
}


//// Copy related methods

//
// Copy the object (for protocol)
// 
// @return the object
// 
- copy
{
  return [super copy];
}

//
// Do a shallow copyo of the object
// 
// @return the object
// 
- shallowCopy
{
  DUnixSocketAddress * copy = [super shallowCopy];
  
  copy->_unix = (struct sockaddr_un *) &(copy->_address);

  return copy;
}


//// Deconstructor

//
// Free the address object
//
// @return the object
//

- free
{
  return [super free];
}


//// Member services

//
// Return the last error
// 
// @return the last error
// 

- (int) error
{  
  return _error;
}

//
// Return the family of the socket address
// 
// @return the family
// 
- (int) family
{
  return DSA_AF_UNIX;
}

//
// Return the socket address
// 
// @return the socket address
// 

- (void *) sockaddr
{
  return _unix;
}

//
// Return the size of the socket address
// 
// @return the size
// 

- (int) size
{
  return _size;
}

//
// Return the port
// 
// @return the port
// 

- (int) port
{
  return 0;
}

//
// Return the filename
// 
// @return a (new) DText object with the filename (or nil for not found)
// 

- (DText *) host
{
  DText *name = [DText new];
  
  [name set :_unix->sun_path];
  
  return name;
}
    
//
// Close the socket address
// 
// @return the object
// 

- (DUnixSocketAddress *) close
{
  if (*_unix->sun_path != EOS)
  {
    unlink(_unix->sun_path);
  }

  return self;
}


//// Socket address setters

//
// Set the filename for an unix socket
// 
// @param filename  the name of the file 
// @param port      the port for the socket
// 
// @return success
// 

- (BOOL) filename :(const char *) name
{
  BOOL ok = NO;
  
  if ((name == NULL) || (*name == EOS))
  {
    WARNING(DW_INVALID_ARG, "name");
  }
  else
  {
    _size = strlen(name) + 1;
      
    ok = (_size < sizeof(_unix->sun_path));
      
    if (ok)
    {
      _unix->sun_family = DSA_AF_UNIX;
      
      strcpy(_unix->sun_path, name);
      
      _size += offsetof(struct sockaddr_un, sun_path);
    }
  }
  
  return ok;
}

//
// Set the socket address with an external socket address
// 
// @param addr      the socket address
// @param size      the size of the socket address
// 
// @return success
// 

- (BOOL) sockaddr :(void *) addr :(int) size
{
  BOOL ok = NO;
  
  struct sockaddr_un *un = (struct sockaddr_un *) addr;
  
  if ((addr == NULL) || (un->sun_family != DSA_AF_UNIX))
  {
    WARNING(DW_INVALID_ARG, "addr");
  }
  else if (size < offsetof(struct sockaddr_un, sun_path))
  {
    WARNING(DW_INVALID_ARG, "size");
  }
  else
  {
    _unix->sun_family = DSA_AF_UNIX;
    
    strcpy(_unix->sun_path, un->sun_path);
    
    _size = size;

    ok = YES;
  }
  
  return ok;
}

@end

#endif


#if _INTERFACE_

#ifdef DSA_AF_INET6

//
// The DInet6SocketAddress class implements a number of methods for using 
// IPv6 socket addresses.
// 

@interface DInet6SocketAddress : Object <DSocketAddressable>
{
@private
  struct sockaddr_in6  _inet6;      // the inet6 socket address
  int                  _error;      // the last error (for host method)
}
#endif
#endif


#ifdef DSA_AF_INET6

@implementation DInet6SocketAddress


//// Constructors

//
// Initialise the socket address
//
// @return the object
//

- (DInet6SocketAddress *) init
{
  [super init];

  memset(&_inet6, 0, sizeof(_inet6));

  _error = 0;
  
  return self;
}

//
// Initialise the socket address with an inet6 address
// 
// @param a1        the first  32 bit of the inet address
// @param a1        the second 32 bit of the inet address
// @param a1        the third  32 bit of the inet address
// @param a1        the fourth 32 bit of the inet address
// @param port      the port
// @param flowInfo  the flow info
// @param scopeId   the scope id
//
// @return the object
//

- (DInet6SocketAddress *) init :(unsigned long) a1 :(unsigned long) a2 :(unsigned long) a3 :(unsigned long) a4 :(int) port :(unsigned long) flowInfo :(unsigned long) scopeId
{
  [self init];
  
  [self set :a1 :a2 :a3 :a4 :port :flowInfo :scopeId];
  
  return self;
}

//
// Initialise the socket address with an inet6 address
// 
// @param address   the 16 bytes of the inet address
// @param port      the port
// @param flowInfo  the flow info
// @param scopeId   the scope id
//
// @return the object
//

- (DInet6SocketAddress *) init :(unsigned char[16]) address :(int) port :(unsigned long) flowInfo :(unsigned long) scopeId
{
  [self init];
  
  [self set :address :port :flowInfo :scopeId];
  
  return self;
}

  
//// Copy constructor

//
// Copy the object (for protocol)
// 
// @return the object
// 
- copy
{
  return [super copy];
}

  
//// Deconstructor

//
// Free the socket object
//
// @return the object
//

- free
{
  return [super free];
}


//// Member services

//
// Return the last error
// 
// @return the last error
// 

- (int) error
{  
  return _error;
}

//
// Return the family of the socket address
// 
// @return the family
// 
- (int) family
{
  return DSA_AF_INET6;
}

//
// Return the socket address
// 
// @return the socket address
// 

- (void *) sockaddr
{
  return &_inet6;
}

//
// Return the size of the socket address
// 
// @return the size
// 

- (int) size
{
  return sizeof(struct sockaddr_in6);
}

//
// Return the port (network format)
// 
// @return the port
// 

- (int) port
{
  return _inet6.sin6_port;
}

//
// Set the port 
// 
// @param port     the port
// 
// @return the object
// 

- (DInet6SocketAddress *) port :(int) port
{
  _inet6.sin6_port = htons(port);
  
  return self;
}

//
// Return the host name 
// 
// @return a (new) text object with the host name (or nil for not found)
// 

- (DText *) host
{
  DText *name = nil;

#if defined(WIN32) || defined(__FreeBSD__)  
  struct hostent *host = gethostbyaddr((const char *)&_inet6, sizeof(struct sockaddr_in6), AF_INET6);
#else
  struct hostent *host = gethostbyaddr(&_inet6, sizeof(struct sockaddr_in6), AF_INET6);
#endif
      
  if (host != NULL)
  {
    name = [DText new];
        
    [name set :host->h_name];
  }
  else
  {
    _error = h_errno;
  }
  
  return name;
}
    

//// Socket address setters

#if _PRIVATE_

#ifndef s6_addr32           // FreeBSD does not define s6_addr16,32
  #define s6_addr32     __u6_addr.__u6_addr32
#endif
#ifndef s6_addr16
  #define s6_addr16     __u6_addr.__u6_addr16
#endif

#endif

//
// Set the socket address with an inet6 address
//
// @param a1        the first  32 bit of the inet address
// @param a2        the second 32 bit of the inet address
// @param a3        the third  32 bit of the inet address
// @param a4        the fourth 32 bit of the inet address
// @param port      the port
// @param flowInfo  the flow info
// @param scopeId   the scope id
//
// @return the object
//

- (DInet6SocketAddress *) set :(unsigned long) a1 :(unsigned long) a2 :(unsigned long) a3 :(unsigned long) a4 :(int) port :(unsigned long) flowInfo :(unsigned long) scopeId
{
  _inet6.sin6_family      = DSA_AF_INET6;
  _inet6.sin6_port        = htons(port);
  _inet6.sin6_flowinfo    = flowInfo;
  _inet6.sin6_scope_id    = scopeId;
  
  _inet6.sin6_addr.s6_addr32[0] = htonl(a1);
  _inet6.sin6_addr.s6_addr32[1] = htonl(a2);
  _inet6.sin6_addr.s6_addr32[2] = htonl(a3);
  _inet6.sin6_addr.s6_addr32[3] = htonl(a4);

  return self;
}

//
// Get the socket address
//
// @param a1        the first  32 bit of the inet address
// @param a2        the second 32 bit of the inet address
// @param a3        the third  32 bit of the inet address
// @param a4        the fourth 32 bit of the inet address
// @param port      the port
// @param flowInfo  the flow info
// @param scopeId   the scope id
//
// @return the object
//

- (DInet6SocketAddress *) get :(unsigned long *) a1 :(unsigned long *) a2 :(unsigned long *) a3 :(unsigned long *) a4 :(int *) port :(unsigned long *) flowInfo :(unsigned long *) scopeId
{
  *port     = ntohs(_inet6.sin6_port);
  *flowInfo = _inet6.sin6_flowinfo;
  *scopeId  =_inet6.sin6_scope_id;
  
  *a1 = ntohl(_inet6.sin6_addr.s6_addr32[0]);
  *a2 = ntohl(_inet6.sin6_addr.s6_addr32[1]);
  *a3 = ntohl(_inet6.sin6_addr.s6_addr32[2]);
  *a4 = ntohl(_inet6.sin6_addr.s6_addr32[3]);

  return self;
}

//
// Set the socket address with an inet6 address
// 
// @param address   the 16 bytes of the inet6 address
// @param port      the port of the address
// @param flowInfo  the flow info
// @param scopeId   the scope id
//
// @return the object
//

- (DInet6SocketAddress *) set :(unsigned char[16]) address :(int) port :(unsigned long) flowInfo :(unsigned long) scopeId
{
  int i;
  
  _inet6.sin6_family      = DSA_AF_INET6;
  _inet6.sin6_port        = htons(port);
  _inet6.sin6_flowinfo    = flowInfo;
  _inet6.sin6_scope_id    = scopeId;

  for (i = 0; i < 16; i++)
  {
    _inet6.sin6_addr.s6_addr[i] = address[i];
  }
  
  return self;
}

//
// Get the socket address
// 
// @param address   the 16 bytes of the inet6 address
// @param port      the port of the address
// @param flowInfo  the flow info
// @param scopeId   the scope id
//
// @return the object
//

- (DInet6SocketAddress *) get :(unsigned char[16]) address :(int *) port :(unsigned long *) flowInfo :(unsigned long *) scopeId
{
  int i;
  
  *port     = ntohs(_inet6.sin6_port);
  *flowInfo = _inet6.sin6_flowinfo;
  *scopeId  = _inet6.sin6_scope_id;

  for (i = 0; i < 16; i++)
  {
    address[i] = _inet6.sin6_addr.s6_addr[i];
  }
  
  return self;
}

//
// Get the socket address (16 bit)
// 
// @param address   the 8 16-bit values of the inet6 address
// @param port      the port of the address
// @param flowInfo  the flow info
// @param scopeId   the scode id
// 
// @return the object
// 
- (DInet6SocketAddress *) get16 :(unsigned[8]) address :(int *) port :(unsigned long *) flowInfo :(unsigned long *) scopeId
{
  int i;

  *port     = ntohs(_inet6.sin6_port);
  *flowInfo = _inet6.sin6_flowinfo;
  *scopeId  = _inet6.sin6_scope_id;

  for (i = 0; i < 8; i++)
  {
    address[i] = ntohs(_inet6.sin6_addr.s6_addr16[i]);
  }
  
  return self;
  
}

//
// Set the socket address with an inet6 host
// 
// @param host      the host name for the inet address
// @param port      the port for the address
// @param flowInfo  the flow info
// @param scopeId   the scope id
// 
// @return the object
// 

- (BOOL) host :(const char *) name :(int) port :(unsigned long) flowInfo :(unsigned long) scopeId
{
  BOOL ok = NO;
  
  if ((name == NULL) || (*name == EOS))
  {
    WARNING(DW_INVALID_ARG, "name");
  }
  else
  {
    struct hostent *host = 0; 
        
    host = gethostbyname(name);
    
    ok = ((host != NULL) && (host->h_addr_list[0] != NULL) && (host->h_addrtype == AF_INET6));
        
    if (ok)
    {
      _inet6.sin6_family     = DSA_AF_INET6;
      _inet6.sin6_addr       = *(struct in6_addr *)(host->h_addr_list[0]);
      _inet6.sin6_port       = htons(port);
      _inet6.sin6_flowinfo   = flowInfo;
      _inet6.sin6_scope_id   = scopeId;
    }
    else
    {
      _error = h_errno;
    }
  }
  
  return ok;
}

//
// Set the socket address with an external socket address
// 
// @param addr      the socket address
// @param size      the size of the socket address
// 
// @return success
// 

- (BOOL) sockaddr :(void *) addr :(int) size
{
  BOOL ok = NO;
  
  struct sockaddr_in6 *inet = (struct sockaddr_in6 *) addr;
  
  if ((addr == NULL) || (inet->sin6_family != DSA_AF_INET6))
  {
    WARNING(DW_INVALID_ARG, "addr");
  }
  else if (size != sizeof(struct sockaddr_in6))
  {
    WARNING(DW_INVALID_ARG, "size");
  }
  else
  {
    _inet6.sin6_family = DSA_AF_INET6;
    
    memcpy(&_inet6, addr, sizeof(struct sockaddr_in6));
  
    ok = YES;
  }
  
  return ok;
}

//
// Set the loopback address for an inet6 socket address
// 
// @param port      the port
// @param flowInfo  the flow info
// @param scopeId   the scope id
// 
// @return the object
// 
- (DInet6SocketAddress *) loopback :(int) port :(unsigned long) flowInfo :(unsigned long) scopeId
{
  _inet6.sin6_family      = DSA_AF_INET6;
  _inet6.sin6_port        = htons(port);
  _inet6.sin6_flowinfo    = flowInfo;
  _inet6.sin6_scope_id    = scopeId;

#ifdef WIN32
  memset(_inet6.sin6_addr.s6_addr, 0, sizeof(_inet6.sin6_addr));

  _inet6.sin6_addr.s6_addr[15] = 1;
#else
  _inet6.sin6_addr        = in6addr_loopback;
#endif

  return self;
}

//
// Set the any address for the inet6 socket address
// 
// @param port      the port
// @param flowInfo  the flow info
// @param scopeId   the scope id
// 
// @return the object
// 
- (DInet6SocketAddress *) any :(int) port  :(unsigned long) flowInfo :(unsigned long) scopeId
{
  _inet6.sin6_family      = DSA_AF_INET6;
  _inet6.sin6_port        = htons(port);
  _inet6.sin6_flowinfo    = flowInfo;
  _inet6.sin6_scope_id    = scopeId;

#ifdef WIN32
  memset(_inet6.sin6_addr.s6_addr, 0, sizeof(_inet6.sin6_addr));
#else
  _inet6.sin6_addr        = in6addr_any;
#endif

  
  return self;
}

//
// Close the socket address
// 
// @return the object
// 

- (DInet6SocketAddress *) close
{
  return self;
}

@end

#endif

/*===========================================================================*/

